#include "wizardnewproject.h"
#include "dlgedittask.h"
#include "pm/project.h"
#include "pm/manager.h"
#include "pm/workrequest.h"
#include "pm/taskhistory.h"
#include "main.h"
#include <wx/msgdlg.h>
#include <boost/foreach.hpp>

#include "res/calculator64.xpm"

WizardNewProject::WizardNewProject(wxWindow* parent)
: wxWizard(parent, wxID_ANY, _("New project wizard"), wxBitmap(calculator64_xpm), wxDefaultPosition, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
{
	m_page1 = new wxWizardPageSimple(this);
	m_panelName = new WizardPageProjectName(m_page1);
	SetPagePanel(m_page1, m_panelName);
	
	wxWizardPageSimple* page2 = new wxWizardPageSimple(this);
	m_panelWorkRequest = new WizardPageWorkRequest(page2);
	SetPagePanel(page2, m_panelWorkRequest);
	wxWizardPageSimple::Chain(m_page1, page2);
	
	wxWizardPageSimple* page3 = new wxWizardPageSimple(this);
	m_panelTasks = new WizardPageTasks(page3);
	SetPagePanel(page3, m_panelTasks);
	wxWizardPageSimple::Chain(page2, page3);

	GetPageAreaSizer()->Add(m_page1);
	
	Connect(wxEVT_WIZARD_FINISHED, wxWizardEventHandler(WizardNewProject::OnFinished), NULL, this);
}

void WizardNewProject::SetPagePanel(wxWizardPage* page, wxPanel* panel)
{
	page->SetExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY);
	wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
	sizer->Add(panel, 1, wxEXPAND|wxALL, 5);
	page->SetSizer(sizer);
	page->Layout();
	sizer->Fit(page);
}

void WizardNewProject::OnFinished(wxWizardEvent& WXUNUSED(event) )
{
	// create project database
	m_filename = m_panelName->GetFileName();
	if (wxFileExists(m_filename)) {
		wxRemoveFile(m_filename);
	}
	if (pm::load(m_filename) == false) {
		wxMessageBox(_("Can't create database file"), _("New project"), wxOK|wxICON_ERROR);
		EndModal(wxID_CANCEL);
		return;
	}
	
	// Create project
	pm::Project project;
	project.name(m_panelName->m_sName);
	if (pm::insert(project) == false) {
		wxMessageBox(_("Can't create the project"), _("New project"), wxOK|wxICON_ERROR);
		EndModal(wxID_CANCEL);
		return;
	}
	
	// Add initial work request
	pm::WorkRequest wr;
	wr.name(m_panelWorkRequest->GetWRName());
	wr.amount(m_panelWorkRequest->GetAmount());
	wr.date(m_panelWorkRequest->GetDate());
	wr.id_project(project.id());
	if (pm::insert(wr) == false) {
		wxMessageBox(_("Can't create the work request"), _("New project"), wxOK|wxICON_ERROR);
		EndModal(wxID_CANCEL);
		return;
	}
	
	// Add inital tasks
	pm::ListTask tasks;
	m_panelTasks->GetTasks(tasks);
	BOOST_FOREACH(pm::Task& task, tasks) {
		task.id_project(project.id());
		if (pm::insert(task) == false) {
			wxMessageBox(_("Can't add task"), _("New project"), wxOK|wxICON_ERROR);
			EndModal(wxID_CANCEL);
			return;
		}
		pm::CreateInitialTaskHistory critAddHistory(task);
		pm::query(critAddHistory);
	}

	// Inform everybody that the project has been loaded
	wxCommandEvent evt(pmEVT_PROJECT_LOADED);
	evt.SetInt(project.id());
	wxPostEvent(wxTheApp, evt);
}


WizardPageProjectName::WizardPageProjectName(wxWindow* parent)
: WizardPageProjectNameGui(parent)
{
}

bool WizardPageProjectName::TransferDataFromWindow()
{
	if (wxPanel::TransferDataFromWindow() == false) {
		return false;
	}
	if (m_sName.empty()) {
		m_editName->SetFocus();
		return false;
	}
	wxString filename = m_fpFile->GetPath();
	if (filename.empty()) {
		m_fpFile->SetFocus();
		return false;
	}
	return true;
}


WizardPageWorkRequest::WizardPageWorkRequest(wxWindow* parent)
: WizardPageWorkRequestGui(parent)
{
}

double WizardPageWorkRequest::GetAmount() const
{
	double amount = 0.0;
	m_sAmount.ToDouble(&amount);
	return amount;
}

bool WizardPageWorkRequest::TransferDataFromWindow()
{
	if (wxPanel::TransferDataFromWindow() == false) {
		return false;
	}
	if (GetWRName().empty()) {
		m_editName->SetFocus();
		return false;
	}
	if (m_sAmount.empty()) {
		m_editAmount->SetFocus();
		return false;
	}
	return true;
}


WizardPageTasks::WizardPageTasks(wxWindow* parent)
: WizardPageTasksGui(parent)
{
	m_listTask->InsertColumn(COL_NAME,      _("Name"));
	m_listTask->InsertColumn(COL_UNIT_COST, _("Unit cost"));
	m_listTask->InsertColumn(COL_QUANTITY,  _("Quantity"));
	m_listTask->InsertColumn(COL_COST,      _("Cost"));
	m_listTask->InsertColumn(COL_DATE,      _("End date"));
}

WizardPageTasks::~WizardPageTasks()
{
	for (int i = 0; i < m_listTask->GetItemCount(); ++i) {
		delete GetTask(i);
	}
}

void WizardPageTasks::GetTasks(pm::ListTask& tasks)
{
	for (int i = 0; i < m_listTask->GetItemCount(); ++i) {
		tasks.push_back(*GetTask(i));
	}
}

pm::Task* WizardPageTasks::GetTask(long item)
{
	return (pm::Task*) m_listTask->GetItemData(item);
}

void WizardPageTasks::AddTask(const pm::Task& task)
{
	long item = m_listTask->InsertItem(m_listTask->GetItemCount(), wxEmptyString);
	SetTask(item, task);
}

void WizardPageTasks::SetTask(long item, const pm::Task& task)
{
	m_listTask->SetItem(item, COL_NAME,      task.name());
	m_listTask->SetItem(item, COL_UNIT_COST, wxString::Format(wxT("%.2f"), task.unit_cost()));
	m_listTask->SetItem(item, COL_QUANTITY,  wxString::Format(wxT("%.2f"), task.quantity()));
	m_listTask->SetItem(item, COL_COST,      wxString::Format(wxT("%.2f"), task.cost()));
	m_listTask->SetItem(item, COL_DATE,      task.end_date().FormatISODate());
	
	pm::Task* pTask = GetTask(item);
	if (pTask) {
		delete pTask;
	}
	m_listTask->SetItemPtrData(item, (wxUIntPtr) new pm::Task(task));
}

bool WizardPageTasks::TransferDataFromWindow()
{
	if (wxPanel::TransferDataFromWindow() == false) {
		return false;
	}
	if (m_listTask->GetItemCount() == 0) {
		return false;
	}
	return true;
}

void WizardPageTasks::OnBtnAdd( wxCommandEvent& WXUNUSED(event) )
{
	DlgNewTask dlg(this, true);
	if (dlg.ShowModal() == wxID_OK) {
		AddTask(dlg.GetTask());
	}
}

void WizardPageTasks::OnBtnDel( wxCommandEvent& WXUNUSED(event) )
{
	long item = m_listTask->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
	if (item == wxNOT_FOUND)
		return;
	delete GetTask(item);
	m_listTask->DeleteItem(item);
}

void WizardPageTasks::OnBtnEdit( wxCommandEvent& WXUNUSED(event) )
{
	long item = m_listTask->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
	if (item == wxNOT_FOUND)
		return;
	pm::Task* pTask = GetTask(item);
	
	DlgUpdateTask dlg(this, *pTask, true);
	if (dlg.ShowModal() == wxID_OK) {
		SetTask(item, dlg.GetTask());
	}
}
